<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="utf-8">
		<base href="../../../" />
		<script src="page.js"></script>
		<link type="text/css" rel="stylesheet" href="page.css" />
	</head>
	<body>
		<h1>使用NPM进行测试（[name]）</h1>

		<p class="desc">
			这篇文章展示了如何将three.js置入[link:https://nodejs.org/en/ node.js]环境中，
			这样你就可以执行自动化测试了。测试可以通过命令行或者类似[link:https://travis-ci.org/ Travis]的CI工具来运行。
		</p>

		<h2>一句话概括</h2>

		<p>
			如果你习惯使用node和npm，
			<code>
				$ npm install three --save-dev
			</code>
			并将
		<code>
			const THREE = require('three');
		</code>
			添加到你的测试中。
		</p>

		<h2>从头创建一个可测试的项目</h2>
		<p>
			如果你不太熟悉这些工具，下面是一个快速入门。（基于linux，在windows上的安装过程会稍稍有点不一样，不过NPM指令是相同的。）
		</p>

		<h3>基本设置</h3>
		<div>
			<ol>
				<li>
					安装[link:https://www.npmjs.org/ npm]和nodejs。最简单的方式一般像这样
					<code>
$ sudo apt-get install -y npm nodejs-legacy
# 修复默认registry URL中任何SSL的问题
$ npm config set registry http://registry.npmjs.org/
					</code>
				</li>

				<li>
					新建一个项目路径
					<code>
						 $ mkdir test-example; cd test-example
					</code>
				</li>

				<li>
					让npm为你创建一份新的项目文件：
					<code>
					 $ npm init
					</code>
					 在所有出现的提示中敲击回车键来接受默认值。
					 这样，一份package.json就建立好了。
				</li><br />

				<li>
					尝试启动测试功能
					<code>
$ npm test
					</code>
					当然，这一定会失败。
					如果你检查一下package.json，test script的定义是这样的
					<code>
						"test": "echo \"Error: no test specified\" && exit 1"
					</code>
				</li>

			</ol>
		</div>

		<h2>添加mocha</h2>
		<div>
			我们将使用[link:https://mochajs.org/ mocha]。

			<ol>
				<li>
					安装mocha
					<code>
$ npm install mocha --save-dev
					</code>
					你会注意到 node_modules/ 被创建了，并且你的依赖都出现在了这里面。
					还有你的package.json被更新了，--save-dev指令向其中加入并更新了devDependencies属性。
				</li><br />

				<li>
					编辑package.json来使用mocha进行测试。当调用测试的时候，我们只想运行mocha并且生成一份详细的报告。
					默认情况下这会运行 test/ 中的任何东西。
					（如果项目中没有 test/ 目录的话，会导致npm报错。你可以通过mkdir test来创建这个目录）
					<code>
						"test": "mocha --reporter list"
					</code>
				</li>

				<li>
					重新运行测试
					<code>
						$ npm test
					</code>

					现在应该就能成功执行了，生成类似 0 passing (1ms) 的报告。
				</li>

			</ol>
		</div>

		<h2>添加three.js</h2>
		<div>
			<ol>
				<li>
					现在添加我们的three.js依赖
					<code>
$ npm install three --save-dev
					</code>
					<ul>
						<li>
							如果你需要three.js的其他版本，使用
							<code>
								$ npm show three versions
							</code>
						  	来确认哪些是可用的。要让npm使用正确的版本，执行
							<code>
 $ npm install three@0.84.0 --save
							</code>
							（例子中用的是0.84.0）。 --save 指令将此加入项目的dependency而不是dev dependency。
							更多信息请参阅<a href="https://www.npmjs.org/doc/json.html">这份文档</a>。
						</li>
					</ul>
				</li>

				<li>
					Mocha会在 test/ 目录中寻找测试文件，所以我们先创建这个目录：
					<code>
					$ mkdir test
					</code>
				</li>

				<li>
					最后我们需要一份JS测试文件来运行。我们就添加一段简单的测试程序，这段程序会检验three.js对象是否能正常工作。
					在 test/ 目录下创建verify-three.js包含以下代码：
<code>
const THREE = require('three');
const assert = require("assert");

describe('The THREE object', function() {
  it('should have a defined BasicShadowMap constant', function() {
    assert.notEqual('undefined', THREE.BasicShadowMap);
  }),

  it('should be able to construct a Vector3 with default of x=0', function() {
    const vec3 = new THREE.Vector3();
    assert.equal(0, vec3.x);
  })
})
</code>
				</li>

				<li>
				最后再次通过$ npm test来测试。这次应该能正确执行上面的代码，并且返回类似：
				<code>
The THREE object should have a defined BasicShadowMap constant: 0ms
The THREE object should be able to construct a Vector3 with default of x=0: 0ms
2 passing (8ms)
				</code>
				</li>
			</ol>
		</div>

		<h2>加入你自己的代码</h2>
		<div>
			你需要做下面三件事：

			<ol>
				<li>
					为你的代码写一段测试程序来检验期望结果，并把它放在 test/ 目录下。
					<a href="https://github.com/air/encounter/blob/master/test/Physics-test.js">这里</a>有一个实际项目的例子。
				</li>

				<li>
					将你的代码以nodejs承认的方式导出，即可以通过require的方式引用。
					参考<a href="https://github.com/air/encounter/blob/master/js/Physics.js">这份代码</a>。
				</li>

				<li>
					在测试程序中通过require引入你自己的代码，就像上面例子中我们通过require('three')来引入一样。
				</li>
			</ol>

			<p>
				第2、3条会根据你组织代码的方式而改变。在上面给出的Physics.js的例子中，导出的部分在代码的最末尾。
				我们将module.exports赋值为一个对象:
			</p>
			<code>
//=============================================================================
// 为了在nodejs中可用
//=============================================================================
if (typeof exports !== 'undefined')
{
  module.exports = Physics;
}
			</code>
		</div>

		<h2>处理依赖</h2>
		<div>
			<p>
				如果你已经在使用require.js或者browserify之类的便捷工具，就跳过这个部分。
			</p>
			<p>
				一般来说，一个three.js项目将在浏览器中运行，浏览器会通过执行一系列script标签来加载模块。
				你自己的文件不用考虑依赖的问题。然而在nodejs环境中，没有一个关联所有文件的index.html，所以你需要显式地加载。
			</p>
			<p>
				如果你要导出的模块还依赖其他文件，你需要告诉node去加载它们。下面是一种方式：
			</p>
			<ol>
				<li>
					在你的模块顶部，检查是否处于nodejs环境中。
				</li>
				<li>
					如果是，那就显式地声明你的依赖。
				</li>
				<li>
					如果不是，你多半处于浏览器环境中。这时候你不需要做任何多余操作。
				</li>
			</ol>
			用Physics.js中的代码举例:
			<code>
//=============================================================================
// 服务器端测试配置
//=============================================================================
if (typeof require === 'function') // 检测nodejs环境
{
  const THREE = require('three');
  const MY3 = require('./MY3.js');
}
			</code>
		</div>

	</body>
</html>
